﻿using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using RBAC.Api.Read.Dto;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace RBAC.Api.Read.Common
{
    /// <summary>
    /// 封装Token获取及刷新机制
    /// </summary>
    public class TokenServices
    {
        private readonly IConfiguration _config;
        private readonly JwtSettings _jwtSettings;

        public TokenServices(IConfiguration config)
        {
            _config = config;
            _jwtSettings = _config.GetSection("JwtSettings").Get<JwtSettings>();
        }

        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string GenerateJwtToken(LoginDto user)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            //负载
            //Claims 指用户信息
            var claims = new[]
            {
                new Claim("Nickname", user.Name),
                new Claim("UserId", user.Id.ToString()),
                new Claim("RoleId", user.RoleId.ToString()),
                new Claim("RoleName", user.RoleName)
            };

            var token = new JwtSecurityToken(
                issuer: _jwtSettings.Issuer,
                audience: _jwtSettings.Audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(Convert.ToInt32(_jwtSettings.AccessTokenExpirationMinutes)),
                signingCredentials: credentials
            );
            //生成授权Token字符
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);
            return strToken;
        }
        /// <summary>
        /// 生成刷新Token
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public string GenRefreshToken(long userId)
        {
            //生成刷新Token 
            var refreshToken = new RefreshToken
            {
                Token = Guid.NewGuid().ToString("N"),
                Expires = DateTime.Now.AddDays(_jwtSettings.RefreshExpireTime),
                Created = DateTime.Now,
                UserId = userId,
            };

            return JsonConvert.SerializeObject(refreshToken);
        }

        /// <summary>
        ///  解析token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        /// <exception cref="SecurityTokenException"></exception>
        public ClaimsPrincipal? GetPrincipalFromExpiredToken(string token)
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = false,
                ValidateIssuer = false,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)),
                ValidateLifetime = false // 这里我们就是要处理过期的token
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);

            if (securityToken is not JwtSecurityToken jwtSecurityToken ||
                !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
                throw new SecurityTokenException("Invalid token");

            return principal;
        }
    }
}
